package com.j.lemon.learn.basic.httpClient;

import okhttp3.*;
import okio.BufferedSink;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.RequestBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 * @Author lijunjun
 * @Date 2019-02-14 11:29
 * @Description
 */
class OkHttp3ClientUtils {
    private static final Logger logger = LoggerFactory.getLogger(OkHttp3ClientUtils.class);

    /**
     * 异步/同步发送get请求
     *
     * @throws InterruptedException
     */
    @Test
    void asyncGet() throws InterruptedException, IOException {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url("https://www.baidu.com");
        Request build = builder.build();
        Call call = okHttpClient.newCall(build);
        //异步发送get请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                logger.info("发送请求失败");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                ResponseBody body = response.body();
                if (null == body) {
                    logger.info("响应为空");
                    return;
                }
                String result = body.string();
                System.out.println(result);
            }
        });
        Thread.sleep(1000);


        //同步发送get请求
        Call call1 = okHttpClient.newCall(build);
        Response execute = call1.execute();
        ResponseBody body = execute.body();
        if (null != body) {
            System.out.println(body.string());
        } else {
            logger.info("响应为空");
        }
    }

    /**
     * 异步/同步发送post请求
     */
    @Test
    void asyncPost() throws IOException, InterruptedException {
        String url = "https://apiqa.st-creditech.com/api/data/mobileNumberCount";
        String uploadUrl = "https://apiqa.st-creditech.com/file/external/fileUpload";

        OkHttpClient client = new OkHttpClient();
        OkHttpClient.Builder builder = getOkHttpClientBuilder(client,uploadUrl);

        OkHttpClient okHttpClient = builder.build();

        //提交String
//---------------------------------------------------------------------------------
//        MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
//        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

//        String data = "hello,i'm jack";
//        RequestBody requestBody = RequestBody.create(mediaType, data);
//---------------------------------------------------------------------------------


        //提交流
//---------------------------------------------------------------------------------
//        RequestBody requestBody = new RequestBody() {
//            @Override
//            public MediaType contentType() {
//                return MediaType.parse("text/x-markdown; charset=utf-8");
//            }
//
//            @Override
//            public void writeTo(BufferedSink bufferedSink) throws IOException {
//                bufferedSink.writeUtf8("测试内容");
//            }
//        };
//---------------------------------------------------------------------------------

        //提交文件
//---------------------------------------------------------------------------------
        MediaType mediaType = MediaType.parse("multipart/form-data; charset=utf-8");
        File file = new File("/Users/lijunjun/1.txt");
        MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
        multipartBodyBuilder.addFormDataPart("partner_code", "shtxdev");
        multipartBodyBuilder.addFormDataPart("partner_key", "12752qw196014AFFE5729CC500Ef396");
        multipartBodyBuilder.addFormDataPart("appType", "file");
        multipartBodyBuilder.addFormDataPart("fileName", "1.txt");
        multipartBodyBuilder.addFormDataPart("fileItem", "1.txt", RequestBody.create(mediaType, file));
        RequestBody requestBody = multipartBodyBuilder.build();
//---------------------------------------------------------------------------------


        //提交表单
//---------------------------------------------------------------------------------
//        FormBody.Builder formBodyBuilder = new FormBody.Builder();
//        formBodyBuilder.add("name","张三");
//        formBodyBuilder.add("mobile","18612787899");
//        formBodyBuilder.add("idCard","41080419910227005X");
//        formBodyBuilder.add("partner_code","shtxdev");
//        formBodyBuilder.add("partner_key","12752qw196014AFFE5729CC500Ef396");
//        RequestBody requestBody = formBodyBuilder.build();

//---------------------------------------------------------------------------------

        Request request = new Request.Builder()
                .url(uploadUrl)
                .post(requestBody)
                .build();

        //异步调用
//        Call call = okHttpClient.newCall(request);
//        call.enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                logger.info("请求失败", e);
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                ResponseBody body = response.body();
//                if (null != body) {
//                    System.out.println(body.string());
//                } else {
//                    logger.info("响应为null");
//                }
//            }
//        });
//        Thread.sleep(2000);

        //同步调用
        Call call1 = okHttpClient.newCall(request);
        Response execute = call1.execute();
        ResponseBody body = execute.body();
        if(null == body) {
            logger.info("响应为null");
            return;
        }

        String string = body.string();
        System.out.println(string);
    }


    //至此，okhttp3的get请求和post请求搞定，看起来没有问题，https和http都可以支持，但是实际上调用https的时候，
    //如果对方服务器的证书是自己制作的，而不是购买的，则会报错，所以需要我们在构建clien的时候，信任所有的证书

    private OkHttpClient.Builder getOkHttpClientBuilder(OkHttpClient okHttpClient,String url){
        OkHttpClient.Builder builder = okHttpClient.newBuilder();
        builder.connectTimeout(2, TimeUnit.SECONDS);
        builder.readTimeout(2, TimeUnit.SECONDS);
        if(StringUtils.isNotBlank(url) && url.startsWith("https")){
            builder.sslSocketFactory(getSSLSocketFactory(),new TrustAll())
                    .hostnameVerifier(getHostnameVerifier());
        }
        return builder;
    }

    public static SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{new TrustAll()},new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static class TrustAll implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    public static HostnameVerifier getHostnameVerifier() {
        return (s, sslSession) -> true;
    }

}
